package interview.findNextNumber;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 寻找全排列下一个数
 */
public class FindNextNumber {
    /**
     * 寻找下一个数
     * @param param 初始化参数
     * @return 返回下一个数
     */
    public static int findNextNumber(int param){
        int[] array = parseArrayList(param);
        int index = findTransferPoint(array);
        if (index == -1) return param;
        int[] copyArray = Arrays.copyOf(array, array.length);
        int[] exchange = exchangeHead(copyArray,index);
        int[] reverse = reverse(exchange,index);
        StringBuffer stringBuffer = new StringBuffer();
        for (int i : reverse) {
            stringBuffer.append(i);
        }
        return Integer.valueOf(stringBuffer.toString());
    }

    private static int[] reverse(int[] exchange, int index) {
        for (int i = index,j = exchange.length - 1; i > j; i++,j--) {
            int temp = exchange[i];
            exchange[i] = exchange[j];
            exchange[j] = temp;
        }
        return exchange;
    }

    private static int[] exchangeHead(int[] copyArray, int index) {
        int head = copyArray[index - 1];
        for (int i = copyArray.length - 1; i > 0; i--) {
            if (head < copyArray[i]){
                copyArray[index - 1] = copyArray[i];
                copyArray[i] = head;
                break;
            }
        }
        return copyArray;
    }

    /**
     * 寻找逆序的下标位置
     * @param list 需要寻找的数组
     * @return 找到逆序开始的前一个下标
     */
    private static int findTransferPoint(int[] list) {
        for (int i = list.length - 1; i >= 0; i--) {
            if (list[i] > list[i - 1]){
                return i;
            }
        }
        return -1;
    }

    /**
     * 将传入的数字转化成一个list
     * @param param 需要转化的数字
     * @return 返回转化完成的list
     */
    private static int[] parseArrayList(int param) {
        String s = String.valueOf(param);
        List<Integer> result = new ArrayList<>();
        String[] split = s.split("");
        for (String s1 : split) {
            result.add(Integer.valueOf(s1));
        }
        return result.stream().mapToInt(Integer::intValue).toArray();
    }

}
